#region

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.OpenApi.Models;

using Swashbuckle.AspNetCore.SwaggerGen;

#endregion

namespace Leo.Core.Swagger
{
    public class SwaggerDocumentFilter : IDocumentFilter
    {
        public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context)
        {
            if (swaggerDoc.Tags == null)
            {
                swaggerDoc.Tags = new List<OpenApiTag>();
            }

            var controllerNamesAndAttributes = context.ApiDescriptions
                .Select(apiDesc => apiDesc.ActionDescriptor as ControllerActionDescriptor)
                .Where(actionDesc => actionDesc != null)
                .GroupBy(actionDesc => actionDesc.ControllerName)
                .Select(group => new KeyValuePair<string, IEnumerable<object>>(group.Key,
                    group.First().ControllerTypeInfo.GetCustomAttributes(true)));
            foreach (var entry in controllerNamesAndAttributes)
            {
                ApplySwaggerTagAttribute(swaggerDoc, entry.Key, entry.Value);
            }
        }

        private void ApplySwaggerTagAttribute(
            OpenApiDocument doc,
            string controllerName,
            IEnumerable<object> customAttributes)
        {
            var attr = customAttributes
                .OfType<ApiDescAttribute>()
                .FirstOrDefault();

            if (attr == null)
            {
                return;
            }

            doc.Tags.Add(new OpenApiTag
            {
                Name = controllerName,
                Description = attr.Name + attr.GroupName,
                ExternalDocs = null
            });
        }
    }
}